package hamsterpolice.todo.model;

import hamsterpolice.todo.data.DataAdapter;
import hamsterpolice.todo.data.DataNotFoundException;
import hamsterpolice.todo.data.Encryption;
import hamsterpolice.todo.data.Model;
import hamsterpolice.todo.data.UnhandledCriteriaException;
import android.content.Context;
import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

public class User extends Model<User> implements Parcelable {
	
	private static final String TAG = "User";

	private String username = null;
	private String passwordHash = null;
	private String firstName = null;
	private String lastName = null;
	private String email = null;
	
	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeLong(getID());
		dest.writeString(username);
		dest.writeString(firstName);
		dest.writeString(lastName);
		dest.writeString(email);
	}

	public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
		public User createFromParcel(Parcel in) {
			return new User(in);
		}

		public User[] newArray(int size) {
			return new User[size];
		}
	};

	private User(Parcel in) {
		setID(in.readLong());
		username = in.readString();
		firstName = in.readString();
		lastName = in.readString();
		email = in.readString();
	}
	
	public User(Context context){
		this(new UserDataAdapter(context));
	}

	public User(DataAdapter<User> dataAdapter){
		super(dataAdapter);
	}
	
	public static User get(Context context, long id) throws DataNotFoundException{
		return get(new UserDataAdapter(context), id);
	}
	
	public static User get(DataAdapter<User> dataAdapter, long id) throws DataNotFoundException{
		Cursor c = null;
		
		try {
			try {
				c = dataAdapter.get(new IDCriterion(id));
			} catch (UnhandledCriteriaException e) {
				Log.e(TAG, "The Data Adapter's get method is unable to handle an IDCriterion.");
				throw new RuntimeException(e);
			}
			
			if(!c.moveToFirst())
				throw new DataNotFoundException();
			
			User cat = new User(dataAdapter);
			cat.setID(dataAdapter.load(c, cat));		
			cat.setNew(false);
			cat.setDirty(false);
			
			return cat;
		}
		finally{
			if(c!=null)
				c.close();
		}
	}
	
	public static User Authenticate(Context context, String username, String password) throws AuthenticationFailureException{
		return Authenticate(new UserDataAdapter(context), username, password);
	}
	
	public static User Authenticate(DataAdapter<User> dataAdapter, String username, String password) throws AuthenticationFailureException{
		Cursor c = null;
		try{
			try {
				c = dataAdapter.get(new AuthenticationCriteria(username, Encryption.hash(password)));
			} catch (UnhandledCriteriaException e) {
				Log.e(TAG, "The Data Adapter's get method is unable to handle AuthenticationCriteria.");
				throw new RuntimeException(e);
			}
			
			if(!c.moveToFirst())
				throw new AuthenticationFailureException();
			
			User cat = new User(dataAdapter);
			cat.setID(dataAdapter.load(c, cat));		
			cat.setNew(false);
			cat.setDirty(false);
			
			return cat;
		}
		finally{
			if(c!=null)
				c.close();
		}
	}

	public String getUsername() {
		return username;
	}
	
	public void setUsername(String username){
		this.username = username;
		setDirty(true);
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
		setDirty(true);
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
		setDirty(true);
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
		setDirty(true);
	}
	
	public String getPasswordHash(){
		return this.passwordHash;
	}
	
	public void setPassword(String password){
		this.passwordHash = Encryption.hash(password);
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		
		if(getFirstName()!=null)
			sb.append(getFirstName());
		
		if(getLastName()!=null){
			if (sb.length()>0) sb.append(" ");
			sb.append(getLastName());
		}
		
		if(sb.length()>0)sb.append(" ");
		sb.append(String.format("(%s[%s])", getUsername(), getID()));
		
		return sb.toString();
	}
}
